<?php
/**
 * 万年历.
 */

namespace bgb;

class Calendar
{
    use Http;

    protected static $_instance;

    protected $_data;

    public function __construct($date = '')
    {
        if (empty($date)) {
            $date = date('Y-01');
        }
        $_data = cache('calendar:' . $date);
        if (empty($_data)) {
            $this->_data = $this->getHoliday($date);
            cache('calendar:' . $date, $this->_data);
        } else {
            $this->_data = $_data;
        }
    }

    /**
     * 获取年度法定节假日
     * @param $date
     * @return array
     * @throws \Exception
     */
    public function getHoliday($date)
    {
        $result = $this->getRequest("http://opendata.baidu.com/api.php?query={$date}&format=json&resource_id=6018", [], [], false);
        $result = mb_convert_encoding($result, 'utf8', 'gbk');
        $result = json_decode($result, true);

        if (isset($result['status']) && $result['status'] == 0) {
            if (!empty($result['data'][0]['holiday'])) {
                $festival = array_column($result['data'][0]['holiday'], 'list');
                $return = [];
                if (is_array($festival)) foreach ($festival as $item) {
                    $return += (array)array_column($item, 'status', 'date');
                }
                $_data = $return;
            } /*else {
                throw new \Exception('节假日获取异常');
            }*/
        } else {
            throw new \Exception('接口异常');
        }
        return ['2021-01-03','2021-02-10','2021-02-11','2021-02-12','2021-02-13','2021-02-14','2021-02-15','2021-02-16','2021-02-17','2021-02-18'];
    }

    /**
     * @param string $date
     * @return Calendar
     */
    public static function getInstance($date = '')
    {
        if (empty($date)) {
            $date = date('Y-01');
        }
        if (!isset(self::$_instance[$date])) {
            self::$_instance[$date] = new self();
        }
        return self::$_instance[$date];
    }

    /**
     * 判断指定日期是否是工作日
     * @param $date
     * @param array $workDate
     * @param array $disabledDate
     * @param bool $hasWeekEnd
     * @return bool
     */
    public function isWork($date, $workDate = [], $disabledDate = [], $hasWeekEnd = true)
    {
        $d = new \DateTime($date);
        $_date = $d->format('Y-m-d');
        $flag = true;
        if (in_array($_date, $disabledDate)) {
            $flag = false;
        } else if (isset($this->_data[$_date])) {
            if ($this->_data[$_date] == 2) {
                $flag = false;
            }
        } else if (in_array($_date, $workDate)) {
            $flag = true;
        } else {
            $w = $d->format('N'); //周几
            $flag = !in_array($w, [6, 7]) ? true : ($hasWeekEnd ? false : true);
        }
        return $flag;
    }

    /**
     * 获取指定日期的下一个工作日
     * @param $date
     * @param int $n
     * @param array $disableDate
     * @param array $workDate
     * @param bool $hasWeekEnd
     * @return false|string
     */
    public function getNextWorkDate($date, $n = 1, $disableDate = [], $workDate = [], $hasWeekEnd = true)
    {
        $time = strtotime($date);
        $i = $t = 1;

        while ($i < 100) {
            $_tmpDate = date('Y-m-d', strtotime("+{$i} days", $time));
            if (($this->isWork($_tmpDate, $workDate, $disableDate, $hasWeekEnd) && !in_array($_tmpDate, $disableDate))) {
                if ($t == $n) {
                    return $_tmpDate;
                } else {
                    $t++;
                    $i++;
                }
            } else {
                $i++;
            }
        }
    }

    public function getData()
    {
        return $this->_data;
    }

    /**
     * 获取法定节假日假期
     * @return array
     */
    public function getHolidayDate()
    {
        return array_keys(array_filter($this->_data, function ($v) {
            return $v == 1;
        }));
    }

}